﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using OnWork.Admin.Util;
using OnWork.Admin.Util.Base;
using OnWork.Admin.Util.Configs;
using Serilog;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
//builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();

//读取配置
var configuration = builder.Configuration;

//注册服务
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.SaveToken = true; //配置保存token  这样再HttpContent就能获取到

    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true, //是否验证Issuer
        ValidIssuer = configuration["JWT:Issuer"], //发行人Issuer
        ValidateAudience = true, //是否验证Audience
        ValidAudience = configuration["JWT:Audience"], //订阅人Audience
        ValidateIssuerSigningKey = true, //是否验证SecurityKey
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:SecretKey"])), //SecurityKey
        ValidateLifetime = true, //是否验证失效时间
        ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值，解决服务器端时间不同步问题（秒）
        RequireExpirationTime = true,
    };

    options.Events = new JwtBearerEvents
    {
        //此处为权限验证失败后触发的事件
        OnChallenge = context =>
        {
            //此处代码为终止.Net Core默认的返回类型和数据结果，这个很重要哦，必须
            context.HandleResponse();

            //自定义自己想要返回的数据结果，我这里要返回的是Json对象，通过引用Newtonsoft.Json库进行转换
            var payload = JsonConvert.SerializeObject(new ReturnModel { Code = 401, Ok = false, Msg = "很抱歉，您无权访问!" });
            //自定义返回的数据类型
            context.Response.ContentType = "application/json";
            //自定义返回状态码，默认为401 我这里改成 200
            //context.Response.StatusCode = StatusCodes.Status200OK;
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            //输出Json数据结果
            context.Response.WriteAsync(payload);
            return Task.FromResult(0);
        }
    };
});

//使用swagger
builder.Services.AddSwaggerGenOnWork(configuration, c =>
{
    //添加Jwt验证设置,添加请求头信息
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Id = "Bearer",
                        Type = ReferenceType.SecurityScheme
                    }
                },
                new List<string>()
            }
        });

    //放置接口Auth授权按钮
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "请输入正确的Token格式： Bearer {token}",
        Name = "Authorization",//jwt默认的参数名称
        In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
        Type = SecuritySchemeType.ApiKey,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
});
//服务器自动注入
builder.Services.AddServicesAutoInjectionOnWork(x => x.FullName.StartsWith("OnWork.Admin"));

//注入配置项目
builder.Services.AddConfig(builder.Configuration);
//异常处理器
builder.Services.AddScoped<ApiExceptionAttribute>();

builder.Services.AddHttpContextAccessor();//注入Http访问

//日志记录 https://www.cnblogs.com/RainFate/p/12073662.html
//string SerilogOutputTemplate = "{NewLine}{{SourceContext}}{NewLine}Date：{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel：{Level}{NewLine}Msg：{Msg}{NewLine}{Exception}" + new string('-', 100);
builder.Services.AddSerilog((services, lc) => lc
    .ReadFrom.Configuration(builder.Configuration)
    .ReadFrom.Services(services)
    .Enrich.FromLogContext());

//允许跨域
builder.Services.AddCors(policy =>
{
    policy.AddPolicy("CorsPolicy", opt => opt
    .AllowAnyOrigin()
    .AllowAnyHeader()
    .AllowAnyMethod()
    .WithExposedHeaders("X-Pagination"));
});



//Microsoft系统日志最低等级为Warning,过滤掉了所有Information日志
//.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
//.MinimumLevel.Override("Microsoft", LogEventLevel.Information)

////记录Net Core系统和EF日志最低级别 (过滤系统日志)
//.MinimumLevel.Override("System", LogEventLevel.Information)
//.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
//.WriteTo.Console()
//.WriteTo.File("00_Logs//log.log",
//            rollingInterval: RollingInterval.Day,
//            outputTemplate: SerilogOutputTemplate,
//            retainedFileCountLimit: 31,
//            retainedFileTimeLimit: TimeSpan.FromDays(2),
//            rollOnFileSizeLimit: true,
//            fileSizeLimitBytes: 52428800 // 50MB
//               ));

var app = builder.Build();

ServiceLocator.Instance = app.Services; //获取Server

app.UseAuthentication();// 认证中间件
app.UseAuthorization();//授权中间件

app.UseHttpsRedirection();

app.UseSwaggerAndUIOnWork();

app.MapControllers();


app.UseCors("CorsPolicy");
app.Run();